<?php

/***  Documentation

    Greqo Base Class Acceptance Test
    
    Revision: $Rev$
    Last Update: $Date: 2009-05-21 04:48:45 +0000 (Thu, 21 May 2009) $
    Author: Tom at klenwell@gmail.com
  
NOTES

______________________________________________________________________________*/

$dn1 = dirname;
$ds = DIRECTORY_SEPARATOR;
$root_dir = $dn1($dn1($dn1(__FILE__))) . $ds;

// import classes to test
require_once($root_dir . 'greqo/greqo.class.php');


class GreqoAcceptanceCase {
    
    /*
        You should only need to add methods beginning test as in testSomething
        as in SimpleTest in modifying this class, though it gives you the
        opportunity for additional stuff.
    */
    
    var $debug = 0;
    var $Log_ = array();
    var $ResultLog = array();
    var $FailLog = array();
    
    function GreqoAcceptanceCase()
    {
        /* php4 constructor */
        $this->start_time = $this->utime();
        $this->Greqo = new Greqo();
    }
    
    function run()
    {
        $this->log('starting test at ' . $this->start_time);
        $TestMethods = $this->_get_test_methods();
        foreach ( $TestMethods as $m ) $this->$m();
        $this->end_time = $this->nf($this->utime() - $this->start_time);
        print $this->reporter();        
    }


    /* TEST METHODS */  
    function testInstance() {
        $this->assert(is_a($this->Greqo, 'Greqo'));
        $this->assert(is_a($this->Greqo->GreqoClient, 'HTTP_Request'));
        $this->assert( !empty($this->Greqo->email) && !empty($this->Greqo->password),
            "login settings loaded for {$this->Greqo->email}" );
    }
    
    function testCache() {
        $id = 'acceptance test';
        $data = 'They also serve who only stand and wait';
        $this->Greqo->load_cacher();
        $this->assert($this->Greqo->Cacher->save($data, $id), "saving cache with id '$id'");
        $cached = $this->Greqo->Cacher->get($id);
        $this->assert($cached == $data, 'cache successfully retrieved');
        $this->assert($this->Greqo->Cacher->remove($id), "cache '$id' deleted");
        $this->assert($this->Greqo->clean_cache(), 'cache cleaned');
    }    
    
    function testHttpRequest() {
        $url = 'http://code.google.com/p/greqo/';
        $this->assert($this->Greqo->get_url($url), "get url $url");
        $this->assert($this->Greqo->GreqoResponse->code_class == 2, 'code class is 2');
    }
    
    function testGetClientLoginToken() {
        $this->Greqo->service = 'blogger';
        $token = $this->Greqo->request_clientlogin_token();
        $this->assert(!empty($token),
            "retrieved (unforced -- saved to session) token: $token");
    }    
    
    function testMail() {
        
        $this->Greqo->load_mailer();
        $this->assert(is_a($this->Greqo->Mailer, 'GmailMailer'),
                          'Mailer loaded and GmailMailer object created');
        
        $subject = 'Greqo Mailer Acceptance Test ' . date('(Y-m-d H:i:s)');
        $body = <<<EMAIL
This is a test of the Greqo GmailMailer, an extension of PHPMailer for use
with Gmail accounts.

For more information on Greqo, see:
http://code.google.com/p/greqo/
EMAIL;
        $SendTo[] = array($this->Greqo->email, 'Greqo Mail Recipient');
        $this->assert($this->Greqo->send_mail($subject, $body, $SendTo),
                          'sending to ' . print_r($SendTo,1));
    }
 

    /* HELPER METHODS */
    function assert($pass, $m='') {
        if ( $pass )
        {
            $this->FailLog[] = 0;
            $this->ResultLog[] = array(
                'pass',
                $m,
                date('Y-m-d H:i:s'),
                $this->caller(),
                $this->rsplit()
            );
        }
        else
        {
            $this->FailLog[] = 1;
            $this->ResultLog[] = array(
                'fail',
                $m,
                date('Y-m-d H:i:s'),
                $this->caller(),
                $this->rsplit()
            );
        }
    }
    
    function log($m) {
       $this->Log_[] = array(
            $m,
            date('Y-m-d H:i:s'),
            $this->caller(1),
            $this->lsplit()
        ); 
    }
    
    function pass($m='') {
        $this->FailLog[] = 0;
        $this->ResultLog[] = array(
            'pass',
            $m,
            date('Y-m-d H:i:s'),
            $this->caller(),
            $this->rsplit()
        );
    }
    
    function fail($m='') {
        $this->FailLog[] = 1;
        $this->ResultLog[] = array(
            'fail',
            $m,
            date('Y-m-d H:i:s'),
            $this->caller(),
            $this->rsplit()
        );
    }
    
    function caller($back=2) {
        /* return array with function and line number going 2 back -- assumes
           will be called by fail, pass, or log */
        $Trace = debug_backtrace();
        #$this->pr($Trace);
        $f = basename($Trace[$back]['file']);
        $l = $Trace[$back]['line'];
        $fx = $Trace[$back]['function'];
        return array($f, $l, $fx);
    }
    
    function utime()
    {
        $utime = microtime();
        return $this->nf(substr($utime,0,9) + substr($utime,-10));
    }
    
    function lsplit()
    {
        static $last;
        $now = $this->utime();
        $last = !empty($last) ? $last : $now;
        $split = $this->nf($now - $last);
        $last = $now;
        return $split;
    }
    
    function rsplit() 
    {
        static $last;
        $now = $this->utime();
        $last = !empty($last) ? $last : $now;
        $split = $this->nf($now - $last);
        $last = $now;
        return $split;
    }    
    
    function nf($float, $dec=4)
    {
        return (float) number_format($float, $dec, '.', '');
    }

    function kill($html, $message='dying')
    {
        $this->print_d(htmlspecialchars($html), '#600');
        print $html;
        die($message);
    }
    
    function echo_d($message, $color='#ccc')
    {
        $_D = debug_backtrace();
        $f = basename($_D[0]['file']);
        $l = $_D[0]['line'];
        $loc = "{$f}:{$l}";
        $out = "<div style='line-height:1.5em; font-family:monospace; color:$color;'>$message <span style='color:#666;'>[$loc]</span></div>";
        $this->_DBG[] = "$loc -> " . strip_tags($message);
        echo $out;
        return;
    }
    
    function print_d($message, $color='#c33')
    {
        if ( $this->debug ) $this->echo_d($message, $color);
        return;
    }
    
    function print_r($Mixed)
    {
        $return = htmlspecialchars(print_r($Mixed, 1));
        $return = "<pre>$return</pre>";
        return $return;
    }
    
    function pr($Mixed, $header='')
    {
        if ( !empty($header) ) $header = "<b>$header</b>";
        $return = htmlspecialchars(print_r($Mixed, 1));
        $return = "<pre style='border:1px solid #ccc; background:#f3f3f3; padding:4px;'>$header\n\n$return</pre>";
        $this->echo_d($return, '#333');
    }
    
    function dump()
    {
        echo $this->print_r($this);
        return;
    }
    
    function _get_test_methods()
    {
        $TestMethodList = array();
        $MethodList = get_class_methods(__CLASS__);
        foreach ( $MethodList as $m )
        {   
            if ( substr($m,0,4) != 'test' ) continue;
            $TestMethodList[] = $m;
        }
        return $TestMethodList;
    }
    
    function reporter()
    {
        // log formatting
        $rlog_t = '<p class="%s"><b>%s</b> [%s] (%s) %s</p>';
        $log_t = '<p class="log">[%s (%s) &raquo; %s:%s] <b>%s</b></p>';
        
        // result log
        $result_log = '';
        foreach ($this->ResultLog as $Log) {
            $result_log .= sprintf($rlog_t, $Log[0], $Log[0], $Log[3][2], $Log[4], $Log[1]);
        }
        
        // log
        $log = '';
        foreach ($this->Log_ as $Log) {
            $log .= sprintf($log_t, $Log[1], $Log[3], $Log[2][0], $Log[2][1], $Log[0]);
        }
        
        // suite results
        $suite_result = ( array_sum($this->FailLog) > 0 ) ? 'fail' : 'pass';
        $suite_text = sprintf('passed %s of %s tests',
                              count(array_keys($this->FailLog, 0)),
                              count($this->FailLog));        
        
        // footer
        $footer = "script completed in {$this->end_time} s";        
        
        $html = <<<XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
<head>
<title>Klenwell Functional Test: %s</title>
<style>
body { font-family:arial,sans-serif; }
h2 { margin:0 0 8px; }
h3 { padding:4px; margin:0 0 12px; font-size:1.2em; border-width:2px 0; border-style:solid; }
.fail { background:#ffeeee; color:#660000; border-color:#ff0000; }
.pass { background:#eeffee; color:#006600; border-color:#00ff00; }
p { margin:0; }
pre .pass { margin:0; padding:3px; border-bottom:1px solid #00ff00; }
pre .pass b { color:#00ff00; }
pre .fail { margin:0; padding:3px; border-bottom:1px solid #ff0000; }
pre .fail b { color:#cc0000; }
.log { margin:0; padding:3px;
 background:#eee; border-bottom:1px solid #ccc; color:#666; 
}
h6.footer {
 margin:0; padding:4px; font-family:monospace; color:#36f;
 border:1px solid #36f; border-width:1px 0;
 font-weight:normal; background:#f3f6ff;
}
</style>
</head>
<body>
<h1>%s</h1>

<h3 class="%s">%s &raquo; %s</h3>

<h2>Tests</h2>
<pre>%s</pre>
<h2>Log</h2><pre>%s</pre>
<h6 class="footer">%s</h6>
</body>
</html>
XHTML;

        return sprintf($html, __CLASS__, __CLASS__,
                        $suite_result,
                        ucwords($suite_result),
                        $suite_text,
                        $result_log,
                        $log,
                        $footer);
    }
}


$Test = &new GreqoAcceptanceCase();
print $Test->run();
?>
